home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 …ember: Reference Library / Apple Developer Reference Library (December 1999) (Disk 1).iso / pc / what's new / sample code / graphics 2d / new newgworld / new newgworld.c < prev    next >
Encoding:
Text File  |  1999-10-24  |  17.8 KB  |  645 lines

  1. /*
  2.     File:        New NewGWorld.c
  3.  
  4.     Contains:    Sample application demonstrating the use of the new version of the NewGWorld routine
  5.  
  6.     Written by:    Geoff Stahl (ggs)
  7.  
  8.     Copyright:    Copyright (c) 1999 Apple Computer, Inc., All Rights Reserved.
  9.  
  10.                 You may incorporate this Apple sample source code into your program(s) without
  11.                 restriction. This Apple sample source code has been provided "AS IS" and the
  12.                 responsibility for its operation is yours. You are not permitted to redistribute
  13.                 this Apple sample source code as "Apple sample source code" after having made
  14.                 changes. If you're going to re-distribute the source, we require that you make
  15.                 it clear in the source that the code was descended from Apple sample source
  16.                 code, but that you've made changes.
  17.  
  18. */
  19.   
  20. // system includes ----------------------------------------------------------
  21.  
  22. #include <MacMemory.h>
  23. #include <Events.h>
  24. #include <Fonts.h>
  25. #include <Windows.h>
  26. #include <TextEdit.h>
  27. #include <Dialogs.h>
  28. #include <Devices.h>
  29. #include <Sound.h>
  30. #include <SoundInput.h>
  31. #include <ToolUtils.h>
  32. #include <OSUtils.h>
  33. #include <LowMem.h>
  34. #include <Gestalt.h>
  35.  
  36. #include <stdlib.h>
  37.  
  38. // project includes ---------------------------------------------------------
  39.  
  40.  
  41.  
  42. // statics/globals (internal only) ------------------------------------------
  43.  
  44. // Menu defs
  45. enum 
  46. {
  47.     kMenuApple = 128,
  48.     kMenuFile = 129,
  49.     
  50.     kAppleAbout = 1,    
  51.     kFileInVRAM = 1,                        // allocate buffer in VRAM
  52.     kFileInAGP,                                // allocate buffer in AGP memory
  53.     kFileInSystem,                            // allocate buffer in system memory
  54.     kFileTest,                                // run blitting test
  55.     kFileQuit                                // quit
  56. };
  57.  
  58. enum
  59. {
  60.                                             // Initial Window Constants
  61.     kWindowHeight = 400,                    //   "
  62.     kWindowWidth = 500,                        //   "
  63.     kWindowOffset = 100                        //   "
  64. };
  65.  
  66. enum
  67. {
  68.     kNoWhere = 0,                            // where is the off screen
  69.     kInVRAM,
  70.     kInAGP,
  71.     kInSystem
  72. };
  73.  
  74. Boolean gDone = false;                        // is app done
  75. SInt32 gSleepTime = 60;                        // yield time
  76.  
  77. WindowPtr gpWindow = NULL;                    // main window
  78. GWorldPtr gpGWOffScreen = NULL;                // main window offscreen scratch
  79. short gwLocOffscreen = 0;                    // curretn offscreen location
  80.  
  81. Boolean gNewNewGWorld = false;                // can we allocate in VRAm or AGP memory?
  82.  
  83.  
  84. // functions Prototypes (internal/private) -----------------------------------
  85.  
  86. // returns GDHandle that window resides on (most of it anyway)
  87. GDHandle GetWindowDevice (WindowPtr pWindow);
  88. // checks and allocates (if required) a new GWorld size of pWindow in memory type target; returns true if (re)allocated
  89. Boolean BuildOffscreen (GWorldPtr * ppGWorld, WindowPtr pWindow, short * target);
  90. // fills offscreen buffer with random bright color
  91. void FillOffscreen (GWorldPtr pGWorld);
  92. // checks offscreen and blits it to the front
  93. void BlitToWindow (GWorldPtr pGWorld, WindowPtr pWindow, short * pLocation);
  94. // checks buffer and then runs 200 iteration CopyBits test offscreen to on and reprots results
  95. void RunTest (void);
  96. // Forces offscreen allocation (if different than current) in memory type specified and sets menu flag
  97. void AllocBuffer (short target);
  98.  
  99. // standard stuff
  100. void InitToolbox(void);                                                    // standard inits
  101. Boolean SetUp (void);                                                    // application setup
  102. void DoMenu (SInt32 menuResult);                                        // menu event handler
  103. void DoKey (SInt8 theKey, SInt8 theCode);                                // key down handling
  104. void DoUpdate (WindowPtr pWindow);                                        // draw from off screen to on and updates control postions on screen for events
  105. void DoEvent (void);                                                    // event handler
  106. void CleanUp (void);                                                    // clean ups after application
  107.  
  108. // functions (internal/private) ---------------------------------------------
  109.  
  110. // returns GDHandle that window resides on (most of it anyway)
  111.  
  112. GDHandle GetWindowDevice (WindowPtr pWindow)
  113. {
  114.     GrafPtr pgpSave;
  115.     Rect rectWind, rectSect;
  116.     long greatestArea, sectArea;
  117.     GDHandle hgdNthDevice, hgdZoomOnThisDevice;
  118.     GetPort (&pgpSave);
  119.     SetPort (pWindow);
  120.     rectWind = pWindow->portRect;
  121.     LocalToGlobal ((Point*)& rectWind.top);    // convert to global coordinates
  122.     LocalToGlobal ((Point*)& rectWind.bottom);
  123.     hgdNthDevice = GetDeviceList ();
  124.     greatestArea = 0;     // initialize to 0
  125.     // check window against all gdRects in gDevice list and remember 
  126.     //  which gdRect contains largest area of window}
  127.     while (hgdNthDevice)
  128.     {
  129.         if (TestDeviceAttribute (hgdNthDevice, screenDevice))
  130.             if (TestDeviceAttribute (hgdNthDevice, screenActive))
  131.             {
  132.                 // The SectRect routine calculates the intersection 
  133.                 //  of the window rectangle and this gDevice 
  134.                 //  rectangle and returns TRUE if the rectangles intersect, 
  135.                 //  FALSE if they don't.
  136.                 SectRect(&rectWind, &(**hgdNthDevice).gdRect, &rectSect);
  137.                 // determine which screen holds greatest window area
  138.                 //  first, calculate area of rectangle on current device
  139.                 sectArea = (long)(rectSect.right - rectSect.left) * (rectSect.bottom - rectSect.top);
  140.                 if ( sectArea > greatestArea )
  141.                 {
  142.                     greatestArea = sectArea;    // set greatest area so far
  143.                     hgdZoomOnThisDevice = hgdNthDevice;    // set zoom device
  144.                 }
  145.                 hgdNthDevice = GetNextDevice(hgdNthDevice);
  146.             }
  147.     }     // of WHILE
  148.     SetPort (pgpSave);
  149.     return hgdZoomOnThisDevice;
  150. }
  151.  
  152. // --------------------------------------------------------------------------
  153.  
  154. // checks and allocates (if required) a new GWorld size of pWindow in memory type target; returns true if (re)allocated
  155. // Currently, this routine checks to see if the GWorld is NULL, the PixMap is NULL, the baseAddr is NULL, the GDevice of the PixMap
  156. //   and the window do not match, and if the color depths are not the same.  If any of the previous is true the GWorld is re-allocated.
  157.  
  158. Boolean BuildOffscreen (GWorldPtr * ppGWorld, WindowPtr pWindow, short * location)
  159.     GDHandle hgdWindow = GetWindowDevice (pWindow);    // window GDevice
  160.     short wPixDepth = (**((CGrafPtr)pWindow)->portPixMap).pixelSize; // window pixel depth
  161.     Boolean fMustRebuild = false;
  162.     
  163.     if (NULL == *ppGWorld) // if GWorld passed in is not allocated
  164.         fMustRebuild = true;
  165.     else
  166.     {
  167.         PixMapHandle hPixmap = GetGWorldPixMap (*ppGWorld);
  168.         if ((NULL == hPixmap) || (NULL == GetPixBaseAddr (hPixmap))) // if pixmap handle is NULL or pixmap base address is NULL
  169.             fMustRebuild = true;
  170.         else if (GetGWorldDevice(*ppGWorld) != hgdWindow) // if GWorld not on same device as window
  171.             fMustRebuild = true;
  172.         else if ((**hPixmap).pixelSize != wPixDepth) // if color depths are not the same
  173.             fMustRebuild = true;
  174.     }
  175.     
  176.     if (fMustRebuild) // must rebuild
  177.     {    
  178.         if (NULL != *ppGWorld) // if we have an allocated GWorld
  179.         {
  180.             DisposeGWorld (*ppGWorld);    // dump our current GWorld
  181.             *ppGWorld = NULL;
  182.         }
  183.         switch (*location) // where to we want to put it
  184.         {
  185.             case kInVRAM:
  186.                 if (noErr == NewGWorld (ppGWorld, wPixDepth, &pWindow->portRect, NULL, hgdWindow, noNewDevice | useDistantHdwrMem))                
  187.                     break;
  188.                 // we failed with VRAM, signal that and drop to AGP
  189.                 SysBeep (30);
  190.                 *location = kInAGP;
  191.             case kInAGP:
  192.                 if (noErr == NewGWorld (ppGWorld, wPixDepth, &pWindow->portRect, NULL, hgdWindow, noNewDevice | useLocalHdwrMem))
  193.                     break;
  194.                 // we failed with AGP, signal that and drop to system memory
  195.                 SysBeep (30);
  196.                 *location = kInSystem;
  197.             case kInSystem:
  198.             default:
  199.                 if (noErr != NewGWorld (ppGWorld, wPixDepth, &pWindow->portRect, NULL, hgdWindow, noNewDevice | keepLocal))
  200.                 {
  201.                     // we failed with system thus we can't allocate our GWorld, signal that, indicate no location and drop to debugger
  202.                     SysBeep (30);
  203.                     *location = kNoWhere;
  204.                     DebugStr ("\pUnable to allocate off screen image");
  205.                     return false; // nothing was allocated
  206.                 }
  207.         } 
  208.         return true; // we rebuilt our GWorld
  209.     }
  210.     return false; // everything is okay
  211. }
  212.  
  213. // --------------------------------------------------------------------------
  214.  
  215. // fills offscreen buffer with random bright color
  216.  
  217. void FillOffscreen (GWorldPtr pGWorld)
  218. {
  219.     static RGBColor rgbColorOld;
  220.     GDHandle hGDSave;
  221.     CGrafPtr pCGrafSave;
  222.     Rect rectSource = (pGWorld->portRect);
  223.     RGBColor rgbColor;
  224.     
  225.     do 
  226.         rgbColor.red = (Random () + 32767) / 2 + 32767;
  227.     while (abs (rgbColor.red - rgbColorOld.red) <  3000);    
  228.     do 
  229.         rgbColor.green = (Random () + 32767) / 2 + 32767;
  230.     while (abs (rgbColor.green - rgbColorOld.green) <  3000);
  231.     do 
  232.         rgbColor.blue = (Random () + 32767) / 2 + 32767;
  233.     while (abs (rgbColor.blue - rgbColorOld.blue) <  3000);
  234.     
  235.     rgbColorOld = rgbColor;
  236.  
  237.     GetGWorld (&pCGrafSave, &hGDSave);
  238.     SetGWorld (pGWorld, NULL);
  239.     if (LockPixels (GetGWorldPixMap (pGWorld)))
  240.     {
  241.         // draw some background
  242.         EraseRect (&rectSource);
  243.         RGBForeColor (&rgbColor);
  244.         PaintRect (&rectSource);
  245.         UnlockPixels (GetGWorldPixMap (pGWorld));
  246.     }
  247.     SetGWorld (pCGrafSave, hGDSave);
  248. }
  249.  
  250. // --------------------------------------------------------------------------
  251.  
  252. // checks offscreen and blits it to the front
  253.  
  254. void BlitToWindow (GWorldPtr pGWorld, WindowPtr pWindow, short * pLocation)
  255. {
  256.     Rect rectDest = ((GrafPtr)pWindow)->portRect;
  257.     Rect rectSource = ((GrafPtr)pWindow)->portRect;
  258.     GrafPtr pCGrafSave;
  259.     
  260.     // check to ensure we have a valid offscreen and rebuild if required
  261.     if (BuildOffscreen (&pGWorld, pWindow, pLocation))
  262.         FillOffscreen (pGWorld);
  263.     
  264.     // blit
  265.     GetPort (&pCGrafSave);
  266.     SetPort ((GrafPtr) pWindow);
  267.     if (LockPixels (GetGWorldPixMap (pGWorld)))
  268.     {
  269.         CopyBits (&((GrafPtr)pGWorld)->portBits, &pWindow->portBits, &rectSource, &rectDest, srcCopy, NULL);
  270.         UnlockPixels (GetGWorldPixMap (pGWorld));
  271.     }
  272.     else
  273.         SysBeep (30);
  274.     SetPort (pCGrafSave);
  275. }
  276.  
  277. // --------------------------------------------------------------------------
  278.  
  279. // checks buffer and then runs 200 iteration CopyBits test offscreen to on and reprots results
  280.  
  281. void RunTest (void)
  282. {
  283.     Str255 str = "\p";
  284.     Rect rectDest = ((GrafPtr)gpWindow)->portRect;
  285.     Rect rectSource = ((GrafPtr)gpWindow)->portRect;
  286.     GrafPtr pCGrafSave;
  287.     long time;
  288.     short i;
  289.  
  290.     BlitToWindow (gpGWOffScreen, gpWindow, &gwLocOffscreen);
  291.  
  292.     GetPort (&pCGrafSave);
  293.     SetPort ((GrafPtr) gpWindow);
  294.     if (LockPixels (GetGWorldPixMap (gpGWOffScreen)))
  295.     {
  296.         time = TickCount ();
  297.         for (i = 0; i < 200; i++)
  298.             CopyBits (&((GrafPtr)gpGWOffScreen)->portBits, &gpWindow->portBits, &rectSource, &rectDest, srcCopy, NULL);
  299.         time = TickCount () - time;
  300.         time = 200 * 60 / time;
  301.  
  302.         NumToString (rectSource.right - rectSource.left, str);
  303.         MoveTo (10, 20);
  304.         DrawString (str);
  305.         MoveTo (43, 20);
  306.         DrawString ("\px");
  307.         NumToString (rectSource.bottom - rectSource.top, str);
  308.         MoveTo (56, 20);
  309.         DrawString (str);
  310.         NumToString (time, str);
  311.         MoveTo (10, 35);
  312.         DrawString (str);
  313.         MoveTo (48, 35);
  314.         DrawString ("\pfps");
  315.         MoveTo (10, 50);
  316.         switch (gwLocOffscreen)
  317.         {
  318.             case kInVRAM:
  319.                 DrawString ("\pIn VRAM");
  320.                 break;
  321.             case kInAGP:
  322.                 DrawString ("\pIn AGP memory");
  323.                 break;
  324.             case kInSystem:
  325.                 DrawString ("\pIn system memory");
  326.                 break;
  327.             default:
  328.                 break;
  329.         }
  330.         UnlockPixels (GetGWorldPixMap (gpGWOffScreen));
  331.     }
  332.     else
  333.     {
  334.         SysBeep (30);
  335.         MoveTo (10, 20);
  336.         DrawString ("\pBlit test failed.");
  337.     }
  338.     SetPort (pCGrafSave);
  339. }
  340.  
  341. // --------------------------------------------------------------------------
  342.  
  343. // forces offscreen allocation (if different than current) in memory type specified and sets menu flag
  344.  
  345. void AllocBuffer (short location)
  346. {
  347.     MenuHandle hMenu;
  348.     short i;
  349.     
  350.     // check to see if we are allocated in the desired buffer
  351.     if (location != gwLocOffscreen) 
  352.     { 
  353.         // dispose to force a rebuild
  354.         if (gpGWOffScreen)
  355.             DisposeGWorld (gpGWOffScreen);
  356.         gpGWOffScreen = NULL;
  357.         gwLocOffscreen = location;
  358.     }
  359.     // ensure we are properly built
  360.     if (BuildOffscreen (&gpGWOffScreen, gpWindow, &gwLocOffscreen))
  361.     {
  362.         FillOffscreen (gpGWOffScreen);
  363.         BlitToWindow (gpGWOffScreen, gpWindow, &gwLocOffscreen);
  364.     }
  365.     
  366.     // set menus
  367.     hMenu = GetMenuHandle (kMenuFile);
  368.     for (i = kFileInVRAM; i <= kFileInSystem; i++)
  369.         CheckMenuItem (hMenu, i, false);
  370.     CheckMenuItem (hMenu, gwLocOffscreen, true);
  371. }
  372.  
  373. // --------------------------------------------------------------------------
  374.  
  375. void InitToolbox()
  376. {
  377.     MenuHandle menu;
  378.  
  379.     MaxApplZone ();
  380.  
  381.     InitGraf((Ptr) &qd.thePort);
  382.     InitFonts();
  383.     InitWindows();
  384.     InitMenus();
  385.     TEInit();
  386.     InitDialogs(nil);
  387.     InitCursor();
  388.     
  389.     qd.randSeed =  TickCount();
  390.  
  391.     // Init Menus
  392.     menu = NewMenu (kMenuApple, "\p\024");            // new  apple menu
  393.     InsertMenu (menu, 0);                            // add menu to end
  394.     AppendResMenu(menu, 'DRVR');
  395.     
  396.     menu = NewMenu (kMenuFile, "\pFile");            // new menu
  397.     InsertMenu (menu, 0);                            // add menu to end
  398.     AppendMenu (menu, "\pAllocate In VRAM;Allocate In AGP Memory;Allocate In System Memory;Run Blit Test;Quit/Q");         // add items
  399.     
  400.     DrawMenuBar();
  401.  
  402. // --------------------------------------------------------------------------
  403.  
  404. Boolean SetUp (void)
  405. {
  406.     Rect rectWindow;
  407.     MenuHandle hMenu;
  408.     long versionSystem;
  409.     short i;
  410.     
  411.     InitToolbox ();
  412.  
  413.     SetRect (&rectWindow, 0, 0, kWindowWidth, kWindowHeight);
  414.     OffsetRect (&rectWindow, kWindowOffset, kWindowOffset);
  415.     gpWindow = NewCWindow (NULL, &rectWindow, "\pNew NewGWorld Test", true, kWindowGrowDocumentProc, (WindowPtr) -1, false, 0);
  416.  
  417.     gNewNewGWorld = false;
  418.     // this will work 9.x
  419.     Gestalt (gestaltSystemVersion, &versionSystem);
  420.     if (0x00000900 == (versionSystem & 0x00000FF00))
  421.         gNewNewGWorld = true;
  422.     else
  423.     {
  424.         // now it is tricky
  425.         // we will try to allocate in VRAM and find out where the allocation really ended up.
  426.         GWorldPtr pgwTest = NULL;
  427.         Rect rectTest = {0, 0, 10, 10};
  428.         short wPixDepth = (**((CGrafPtr)gpWindow)->portPixMap).pixelSize; // window pixel depth
  429.         GDHandle hgdWindow = GetWindowDevice (gpWindow);    // window GDevice
  430.         if ((noErr == NewGWorld (&pgwTest, wPixDepth, &rectTest, NULL, hgdWindow, noNewDevice | useDistantHdwrMem)) &&
  431.             (pgwTest) && // if we had a good allocation
  432.             (GetZone () != HandleZone ((Handle)((**pgwTest->portPixMap).baseAddr)))) // if we did not allocate in our zone
  433.             gNewNewGWorld = true;    
  434.         if (pgwTest)
  435.             DisposeGWorld (pgwTest);
  436.     }        
  437.     if (!gNewNewGWorld)
  438.     {
  439.         hMenu = GetMenuHandle (kMenuFile);
  440.         for (i = kFileInVRAM; i <= kFileInAGP; i++)
  441.              DisableItem (hMenu, i);
  442.         AllocBuffer (kInSystem);
  443.     }
  444.     else
  445.         AllocBuffer (kInVRAM);
  446.     return true;
  447. }
  448.  
  449. // --------------------------------------------------------------------------
  450.  
  451. void DoMenu (SInt32 menuResult)
  452. {
  453.     SInt16 theMenu;
  454.     SInt16 theItem;
  455.     Str255 daName;
  456.     MenuRef theMenuHandle;
  457.         
  458.     theMenu = HiWord(menuResult);
  459.     theItem = LoWord(menuResult);
  460.     theMenuHandle = GetMenuHandle(theMenu);
  461.  
  462.     switch (theMenu)
  463.     {
  464.         case kMenuApple:
  465.             switch (theItem)
  466.             {
  467.                 case kAppleAbout:
  468.                     break;
  469.                 default:
  470.                     OpenDeskAcc(daName);
  471.                     break;
  472.             }
  473.             break;
  474.         case kMenuFile:
  475.             switch (theItem)
  476.             {
  477.                 case kFileInVRAM:
  478.                     AllocBuffer (kInVRAM);
  479.                     break;
  480.                 case kFileInAGP:
  481.                     AllocBuffer (kInAGP);
  482.                     break;
  483.                 case kFileInSystem:
  484.                     AllocBuffer (kInSystem);
  485.                     break;
  486.                 case kFileTest:
  487.                     RunTest ();
  488.                     break;
  489.                 case kFileQuit:
  490.                     gDone = true;
  491.                     break;
  492.             }
  493.             break;
  494.     }
  495.     HiliteMenu(0);
  496.     DrawMenuBar();
  497. }
  498.  
  499. // --------------------------------------------------------------------------
  500.  
  501. void DoKey (SInt8 theKey, SInt8 theCode)
  502. {
  503.     #pragma unused (theKey, theCode)
  504. }
  505.  
  506. // --------------------------------------------------------------------------
  507.  
  508. void DoUpdate (WindowPtr pWindow)
  509. {
  510.     BlitToWindow (gpGWOffScreen, pWindow, &gwLocOffscreen);
  511. }
  512.  
  513. // --------------------------------------------------------------------------
  514.  
  515. void DoEvent (void)
  516. {
  517.     EventRecord theEvent;
  518.     Rect rectGrow;
  519.     WindowRef whichWindow;
  520.     long grow;
  521.     SInt32 menuResult;
  522.     SInt16 whatPart;
  523.     SInt8 theKey;
  524.     SInt8 theCode;
  525.     
  526.     if (WaitNextEvent(everyEvent, &theEvent, gSleepTime, NULL))
  527.     {
  528.         switch (theEvent.what)
  529.         {
  530.             case mouseDown:
  531.                 whatPart = FindWindow(theEvent.where, &whichWindow);
  532.                 switch (whatPart)
  533.                 {
  534.                     case inGoAway:
  535.                         break;
  536.                     case inMenuBar:
  537.                         DrawMenuBar();
  538.                         menuResult = MenuSelect(theEvent.where);
  539.                         if (HiWord(menuResult) != 0)
  540.                             DoMenu(menuResult);
  541.                         break;
  542.                     case inDrag:
  543.                         DragWindow (whichWindow, theEvent.where, &(**LMGetGrayRgn()).rgnBBox);
  544.                         // ensure we are properly built
  545.                         if (BuildOffscreen (&gpGWOffScreen, gpWindow, &gwLocOffscreen))
  546.                         {
  547.                             FillOffscreen (gpGWOffScreen);
  548.                             BlitToWindow (gpGWOffScreen, gpWindow, &gwLocOffscreen);
  549.                         }
  550.                         break;
  551.                     case inGrow:
  552.                         SetRect (&rectGrow, 100, 100, 20000, 20000);
  553.                         grow = GrowWindow (whichWindow, theEvent.where, &rectGrow);
  554.                         if (grow)
  555.                         {
  556.                             SizeWindow (whichWindow, grow & 0x0000FFFF, grow >> 16, true);
  557.                             // ensure offscreen buffer is reallocated
  558.                             if (gpGWOffScreen)
  559.                                 DisposeGWorld (gpGWOffScreen);
  560.                             gpGWOffScreen = NULL;
  561.                             AllocBuffer (gwLocOffscreen);
  562.                             SetPort (whichWindow);
  563.                             InvalRect (&whichWindow->portRect);                // redraw all
  564.                         }
  565.                         break;
  566.                     case inSysWindow:
  567.                         SystemClick(&theEvent, whichWindow);
  568.                         break;
  569.                 }
  570.                 break;
  571.             case keyDown:
  572.             case autoKey:
  573.                 theKey = theEvent.message & charCodeMask;
  574.                 theCode = (theEvent.message & keyCodeMask) >> 8;
  575.                 if ((theEvent.modifiers & cmdKey) != 0)
  576.                 {
  577.                     menuResult = MenuKey(theKey);
  578.                     if (HiWord(menuResult) != 0)
  579.                         DoMenu (menuResult);
  580.                 }
  581.                 else
  582.                     DoKey (theKey, theCode);
  583.                 break;
  584.             case updateEvt:
  585.                 BeginUpdate((WindowPtr) theEvent.message);
  586.                 DoUpdate((WindowPtr) theEvent.message);
  587.                 EndUpdate((WindowPtr) theEvent.message);
  588.                 break;
  589.             case diskEvt:
  590.                 break;
  591.             case osEvt:
  592.                 break;
  593.  
  594.             case kHighLevelEvent:
  595.                 AEProcessAppleEvent(&theEvent);
  596.                 break;
  597.         }
  598.     }
  599.     else
  600.     {
  601.         // idle tasks
  602.     }
  603. }
  604.  
  605. // --------------------------------------------------------------------------
  606.  
  607. void CleanUp (void)
  608. {
  609.     MenuHandle hMenu;
  610.  
  611.     HideWindow (gpWindow);
  612.     if (gpWindow)
  613.         DisposeWindow (gpWindow);
  614.     gpWindow = NULL;
  615.     
  616.     // this is VERY important since the GWorld may not be in the application heap zone
  617.     // leaked memory here outside the app heap may not be recoverable without a restart
  618.     if (gpGWOffScreen)
  619.         DisposeGWorld (gpGWOffScreen);
  620.     gpGWOffScreen = NULL;
  621.     
  622.     hMenu = GetMenuHandle (kMenuFile);
  623.     DeleteMenu (kMenuFile);
  624.     DisposeMenu (hMenu);
  625.  
  626.     hMenu = GetMenuHandle (kMenuApple);
  627.     DeleteMenu (kMenuApple);
  628.     DisposeMenu (hMenu);
  629. }
  630.  
  631. // --------------------------------------------------------------------------
  632.  
  633. int main (void)
  634. {
  635.     if (SetUp ())
  636.         while (!gDone)
  637.             DoEvent ();
  638.     CleanUp ();
  639.     return 0;
  640. }
  641.  
  642.  
  643.